package com.mioto.ld.module.device.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mioto.ld.communication.mqtt.MqttHelper;
import com.mioto.ld.communication.mqtt.protocol.cache.DeviceInfoCache;
import com.mioto.ld.communication.mqtt.protocol.cache.ReportAttributeCache;
import com.mioto.ld.component.BasePager;
import com.mioto.ld.module.device.model.*;
import com.mioto.ld.module.device.model.app.*;
import com.mioto.ld.module.personal.model.User;
import com.mioto.ld.utils.BaseUtil;
import com.mioto.ld.utils.SpringBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import com.mioto.ld.module.device.dao.DeviceDao;
import com.mioto.ld.module.device.service.IDeviceService;
import javax.annotation.Resource;
import java.util.*;

/**
 *
 * @author mioto
 * @date 2024-05-15 16:13:50
 */
@Service("deviceService")
@Slf4j
public class DeviceServiceImpl implements IDeviceService{

    @Resource
    private DeviceDao deviceDao;

    @Override
    public List<Device> findList(Device device) {
        return deviceDao.findList(device);
    }

    @Override
    public int insert(Device device) {
        return deviceDao.insertIgnoreNull(device);
    }

    @Override
    public int update(Device device) {
        return deviceDao.update(device);
    }

    @Override
    public int updateIgnoreNull(Device device) {
        return deviceDao.updateIgnoreNull(device);
    }

    @Override
    public Device findByColumn(String column, Object value) {
        return deviceDao.findByColumn(column,value);
    }

    @Override
    public int deleteByColumn(String column, Object value) {
        return deviceDao.deleteByColumn(column,value);
    }

    @Override
    public int batchDelete(Integer[] ids) {
        return deviceDao.batchDelete(ids);
    }

    @Override
    public PageInfo<DevicePagerVO> findPager(DeviceSearchDTO device, BasePager basePager) {
        //如果搜索条件中有设备状态筛选,根据状态先查出对应的设备id
        Integer runtimeStatus = device.getRuntimeStatus();
        boolean searchStatus = ObjectUtil.isNotNull(device) && ObjectUtil.isNotNull(runtimeStatus);
        if (searchStatus){
            //查询所有符合条件的设备
            String[] filterSns = deviceDao.findDeviceSns(device, BaseUtil.buildUserFilterCondition());
            String[] searchSns = new String[filterSns.length];
            if (ArrayUtil.isNotEmpty(filterSns)){
                int i = 0;
                //筛选在、离线设备sn作为后面分页查询条件
                for (String filterSn : filterSns) {
                    if (ObjectUtil.equal(runtimeStatus, DeviceStatus.ONLINE)) {
                        if (MqttHelper.containsSn(filterSn)) {
                            searchSns[i++] = filterSn;
                        }
                    } else if (ObjectUtil.equal(runtimeStatus, DeviceStatus.OFFLINE)){
                        if (!MqttHelper.containsSn(filterSn)) {
                            searchSns[i++] = filterSn;
                        }
                    }
                }
                device.setFilterSns(searchSns);
            }
            //如果没有包含在、离线设备的设备列表，返回空数据
            if (ArrayUtil.isAllEmpty(searchSns)){
                return new PageInfo<>(new ArrayList<>(0));
            }
        }
        PageHelper.startPage(basePager.getPage(), basePager.getRows(), basePager.getSortBy());
        List<DevicePagerVO> pager= deviceDao.findPager(device,BaseUtil.buildUserFilterCondition());
        PageInfo<DevicePagerVO> pageInfo = new PageInfo<>(pager);
        if (!pager.isEmpty()) {
            //查询故障状态的设备sn
            device.setStatus(DeviceStatus.FAULT);
            String[] faultSns = deviceDao.findDeviceSns(device, BaseUtil.buildUserFilterCondition());
            for (DevicePagerVO devicePagerVO : pager) {
                //设置搜索结果的设备运行状态
                if (!searchStatus) {
                    if (MqttHelper.containsSn(devicePagerVO.getSn())) {
                        devicePagerVO.setRuntimeStatus(DeviceStatus.ONLINE);
                    }else {
                        devicePagerVO.setRuntimeStatus(DeviceStatus.OFFLINE);
                    }
                }else {
                    devicePagerVO.setRuntimeStatus(runtimeStatus);
                }

                //设置搜索结果的设备状态,默认设为正常状态
                devicePagerVO.setStatus(DeviceStatus.NORMAL);
                if (ArrayUtil.isNotEmpty(faultSns)) {
                    for (String faultSn : faultSns) {
                        if (StrUtil.equals(devicePagerVO.getSn(), faultSn)) {
                            devicePagerVO.setStatus(DeviceStatus.FAULT);
                            break;
                        }
                    }
                }
            }
        }
        return pageInfo;
    }

    @Override
    public String[] findSnsByProductId(Integer productId) {
        return deviceDao.findSnsByProductId(productId);
    }

    @Override
    public String[] findSnsByDeviceIds(String deviceIds) {
        return deviceDao.findSnsByDeviceIds(deviceIds);
    }

    @Override
    public int updateLineDateBySn(String sn, Date onlineDate, Date offlineDate) {
        return deviceDao.updateLineDateBySn(sn,onlineDate,offlineDate);
    }

    @Override
    public DeviceStatusStatisticVO statusStatistics(DeviceSearchDTO device) {
        DeviceStatusStatisticVO deviceStatusStatisticVO = deviceDao.statusStatistics(device,BaseUtil.buildUserFilterCondition());
        if (StrUtil.isNotEmpty(deviceStatusStatisticVO.getDeviceSns())){
            //统计在、离线设备数量
            int onlineCount = 0;
            String[] deviceSns = StrUtil.splitToArray(deviceStatusStatisticVO.getDeviceSns(),StrUtil.C_COMMA);
            int totalCount = deviceSns.length;
            deviceStatusStatisticVO.setTotalCount(totalCount);
            for (String deviceSn : deviceSns) {
                if (MqttHelper.containsSn(deviceSn)){
                    onlineCount++;
                }
            }
            deviceStatusStatisticVO.setOnlineCount(onlineCount);
            deviceStatusStatisticVO.setOfflineCount(totalCount - onlineCount);
            //统计正、异常设备数量
            if (StrUtil.isNotEmpty(deviceStatusStatisticVO.getFaultSns())){
                int faultCount = StrUtil.splitToArray(deviceStatusStatisticVO.getFaultSns(),StrUtil.C_COMMA).length;
                deviceStatusStatisticVO.setFaultCount(faultCount);
                deviceStatusStatisticVO.setNormalCount(totalCount - faultCount);
            }else {
                deviceStatusStatisticVO.setNormalCount(deviceStatusStatisticVO.getTotalCount());
                deviceStatusStatisticVO.setFaultCount(0);
            }

            //搜索条件中包含设备状态
            if (ObjectUtil.isNotNull(device) && ObjectUtil.isNotNull(device.getRuntimeStatus())){
                if (ObjectUtil.equal(device.getRuntimeStatus(),DeviceStatus.OFFLINE)){
                    deviceStatusStatisticVO.setTotalCount(deviceStatusStatisticVO.getOfflineCount());
                    deviceStatusStatisticVO.setOnlineCount(0);
                }else if (ObjectUtil.equal(device.getRuntimeStatus(),DeviceStatus.ONLINE)){
                    deviceStatusStatisticVO.setTotalCount(deviceStatusStatisticVO.getOnlineCount());
                    deviceStatusStatisticVO.setOfflineCount(0);
                }
            }
        }
        return deviceStatusStatisticVO;
    }


    @Override
    public DeviceDetailVO findDetail(Integer deviceId) {
        DeviceDetailVO deviceDetailVO = deviceDao.findDetail(deviceId);
        if (MqttHelper.containsSn(deviceDetailVO.getSn())) {
            deviceDetailVO.setStatus(DeviceStatus.ONLINE);
        }
       /* int faultStatus = deviceDao.findFaultStatus(deviceId);
        if (faultStatus > 0){
            deviceDetailVO.setStatus(DeviceStatus.FAULT);
        }else if (MqttHelper.containsSn(deviceDetailVO.getSn())){
            deviceDetailVO.setStatus(DeviceStatus.ONLINE);
        }*/
        return deviceDetailVO;
    }

    @Override
    public DeviceDetailAppVO findDetailToApp(Integer deviceId) {
        return deviceDao.findDetailToApp(deviceId);
    }

    @Override
    public List<AppDeviceMainPageVO> findAppMainData() {
        User user = BaseUtil.getLoginUser();
        return deviceDao.findAppMainData(BaseUtil.buildUserFilterCondition(),user.getUserType());
    }

    @Override
    public AppDeviceMainPageCounterVO findAppMainDeviceData(Integer productId) {
        AppDeviceMainPageCounterVO pageCounterVO =  deviceDao.findAppMainDeviceData(productId,BaseUtil.buildUserFilterCondition());
        int onlineCount = 0;
        if (ArrayUtil.isNotEmpty(pageCounterVO.getDeviceSns())){
            for (String deviceSn : pageCounterVO.getDeviceSns()) {
                if (MqttHelper.containsSn(deviceSn)){
                    onlineCount++;
                }
            }
        }
        pageCounterVO.setOnlineCount(onlineCount);
        pageCounterVO.setOfflineCount(pageCounterVO.getTotalCount() - onlineCount);
        pageCounterVO.setAddressVOList(deviceDao.findAppMainDeviceAddressData(productId,BaseUtil.buildUserFilterCondition()));
        return pageCounterVO;
    }

    @Override
    public List<AppDeviceListVO> findAppDeviceList(Integer[] deviceIds, int searchType) {
        List<AppDeviceListVO> list = deviceDao.findAppDeviceList(deviceIds);
        //在线状态取实时属性
        if (CollUtil.isNotEmpty(list) && searchType == AppDeviceListSearchType.ONLINE){
            Map<String,Object> attr;
            for (AppDeviceListVO listVO : list) {
                attr = ReportAttributeCache.getAttributes(listVO.getDeviceSn());
                if (CollUtil.isNotEmpty(attr)){
                    listVO.setReportAttribute(JSONUtil.parseObj(attr).toString());
                }
            }
        }
        return list;
    }

    @Override
    public List<AppDeviceMainPageAddressVO> appUserDevices() {
        return deviceDao.appUserDevices(BaseUtil.getLoginUser().getId());
    }

    @Override
    public Device updateOwnerUser(String deviceSn, Integer userId) {
        Device device = deviceDao.findByColumn("sn",deviceSn);
        if (ObjectUtil.isNotNull(device)){
            int result = deviceDao.updateOwnerUser(deviceSn,userId);
            if (result > 0) {
                device.setOwnerUser(userId);
                Device cache = SpringBeanUtil.getBean(DeviceInfoCache.class).get(deviceSn);
                if (ObjectUtil.isNotNull(cache)){
                    cache.setOwnerUser(userId);
                }
            }
        }
        return device;
    }
}